﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Slam.Configuration;
using Slam.Events;
using SlamContext.Cache;
using System.Threading;

namespace Slam.WebControls
{
	public class SlamLoader : WebControl
	{
		private static bool _loaderRunning = false;
		protected override void OnLoad(EventArgs e)
		{
			if (!SlamContext.Cache.ContainsKey(Constants.Cache.ConfiguredTypeCollection, CacheScope.Application) && !_loaderRunning)
			{
				_loaderRunning = true;
				Thread loadTypesThread = new Thread(LoadTypes);
				loadTypesThread.Start(SPContext.Current.Site.Url);
			}
		}

		private void LoadTypes(object siteUrl)
		{
			try
			{
				Dictionary<string, ConfiguredType> configuredTypes = new Dictionary<string, ConfiguredType>();
				Dictionary<string, IItemCreator> creators = new Dictionary<string, IItemCreator>();
				Dictionary<string, IItemDeleter> deleters = new Dictionary<string, IItemDeleter>();
				Dictionary<string, IItemUpdater> updaters = new Dictionary<string, IItemUpdater>();

				SPSecurity.RunWithElevatedPrivileges(delegate()
				{
					using (SPSite elevatedSite = new SPSite(siteUrl.ToString()))
					{
						IConfigurationManager slamConfiguration = ComponentService.GetInstance<IConfigurationManager>();
						DataMapping currentDataMapping = slamConfiguration.DataMapping;
						string siteCollection = elevatedSite.ServerRelativeUrl.TrimStart('/');
						if (!String.IsNullOrEmpty(siteCollection) && slamConfiguration.DataMappings.ContainsKey(siteCollection))
						{
							currentDataMapping = slamConfiguration.DataMappings[siteCollection];
						}

						foreach (var type in currentDataMapping.GetAllTypes())
						{
							SPWeb elevatedWeb = null;
							try
							{
								//If Site is empty, open the Root Web
								if (String.IsNullOrEmpty(type.Site))
								{
									elevatedWeb = elevatedSite.RootWeb;
								}
								else
								{
									elevatedWeb = elevatedSite.AllWebs[type.Site];
								}
							}
							catch
							{
							}

							if (elevatedWeb != null && elevatedWeb.Exists)
							{
								List<string> typeKeys = new List<string>();
								if (!type.ContentType)
								{
									try
									{
										SPList list = null;
										if (!String.IsNullOrEmpty(type.Id))
										{
											list = elevatedWeb.Lists[new Guid(type.Id)];
										}
										else
										{
											list = elevatedWeb.Lists[type.Name];
										}

										if (list != null)
										{
											typeKeys.Add(list.ID.ToString());
										}
									}
									catch
									{
									}

									if (!String.IsNullOrEmpty(currentDataMapping.GetTypeAttribute(type.Id, type.Name, "AllSites")) && currentDataMapping.GetTypeAttribute(type.Id, type.Name, "AllSites").ToLower() == "true")
									{
										try
										{
											for (int i = 0; i < elevatedSite.AllWebs.Count; i++)
											{
												SPWeb subWeb = elevatedSite.AllWebs[i];
												SPList list = null;

												if (!String.IsNullOrEmpty(type.Id))
												{
													list = subWeb.Lists[new Guid(type.Id)];
												}
												else
												{
													list = subWeb.Lists[type.Name];
												}

												if (list != null)
												{
													typeKeys.Add(list.ID.ToString());
												}

												subWeb.Dispose();
											}
										}
										catch
										{
										}
									}
								}
								else //If type is a ContentType
								{
									SPContentType contentType = null;
									try
									{
										contentType = elevatedWeb.ContentTypes[type.Name];
									}
									catch
									{
									}

									if (contentType != null)
									{
										typeKeys.Add(contentType.Id.ToString());
									}
								}

								foreach (string typeKey in typeKeys)
								{
									if (!configuredTypes.ContainsKey(typeKey))
										configuredTypes.Add(typeKey, type);
									if (!creators.ContainsKey(typeKey))
										creators.Add(typeKey, ComponentService.GetInstance<IItemCreator>(siteCollection, elevatedWeb.Name, type.Name));
									if (!deleters.ContainsKey(typeKey))
										deleters.Add(typeKey, ComponentService.GetInstance<IItemDeleter>(siteCollection, elevatedWeb.Name, type.Name));
									if (!updaters.ContainsKey(typeKey))
										updaters.Add(typeKey, ComponentService.GetInstance<IItemUpdater>(siteCollection, elevatedWeb.Name, type.Name));
								}
								elevatedWeb.Dispose();
							}
						}
					}
				});

				if (configuredTypes.Count > 0)
				{
					SlamContext.Cache.Add(Constants.Cache.ConfiguredTypeCollection, configuredTypes, CacheScope.Application);
					SlamContext.Cache.Add(Constants.Cache.ItemCreatorCollection, creators, CacheScope.Application);
					SlamContext.Cache.Add(Constants.Cache.ItemDeleterCollection, deleters, CacheScope.Application);
					SlamContext.Cache.Add(Constants.Cache.ItemUpdaterCollection, updaters, CacheScope.Application);
				}
			}
			catch { }
			_loaderRunning = false;
		}
	}
}
